package com.zjhcsoft.auth.gateway.route.impl;


import com.alibaba.fastjson.JSON;
import com.alibaba.nacos.api.NacosFactory;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.config.listener.Listener;
import com.alibaba.nacos.api.exception.NacosException;
import com.zjhcsoft.auth.gateway.config.NacosGatewayConfig;
import com.zjhcsoft.auth.gateway.route.api.IRouteService;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.Executor;
import javax.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.stereotype.Service;

@Service
@Slf4j
public class NacosRouteServiceImpl implements IRouteService {

  private static final String GATEWAY_ROUTES = "gateway_routes::";

  private ConfigService configService;

  @Autowired
  private NacosGatewayConfig nacosGatewayConfig;

  private Map<String, RouteDefinition> routeDefinitionMaps = new HashMap<>();

  @PostConstruct
  private void loadRouteDefinition() {
    log.info("loadRouteDefinition, 开始初使化路由");
    String configInfo = null;
    try {
      Properties properties = new Properties();
      properties.setProperty("serverAddr", nacosGatewayConfig.getNacosServerAddr());
      properties.setProperty("namespace", nacosGatewayConfig.getNacosNamespace());
      configService = NacosFactory.createConfigService(properties);
      configInfo = configService.getConfig(
          nacosGatewayConfig.getNacosRouteDataId(),
          nacosGatewayConfig.getNacosRouteGroup(),
          NacosGatewayConfig.DEFAULT_TIMEOUT);
    } catch (NacosException e) {
      e.printStackTrace();
    }
    log.info("预计初使化路由, gatewayKeys:{}", configInfo);
    List<RouteDefinition> routeDefinitions = JSON.parseArray(configInfo, RouteDefinition.class);
    for (RouteDefinition routeDefinition : routeDefinitions) {
      log.info("Update route:{}", routeDefinition.toString());
      routeDefinitionMaps.put(routeDefinition.getId(), routeDefinition);
    }

    log.info("共初使化路由信息：{}", routeDefinitionMaps.size());
    dynamicRouteByNacosListener(nacosGatewayConfig.getNacosRouteDataId(),
        nacosGatewayConfig.getNacosRouteGroup());

  }

  @Override
  public Collection<RouteDefinition> getRouteDefinitions() {
    return routeDefinitionMaps.values();
  }

  @Override
  public boolean save(RouteDefinition routeDefinition) {
    routeDefinitionMaps.put(routeDefinition.getId(), routeDefinition);
    log.info("新增路由1条：{},目前路由共{}条", routeDefinition, routeDefinitionMaps.size());
    return true;
  }

  @Override
  public boolean delete(String routeId) {
    routeDefinitionMaps.remove(routeId);
    log.info("删除路由1条：{},目前路由共{}条", routeId, routeDefinitionMaps.size());
    return true;
  }

  public void dynamicRouteByNacosListener(String dataId, String group) {
    try {
      configService.addListener(dataId, group, new Listener() {
        @Override
        public Executor getExecutor() {
          log.info("getExecutor");
          return null;
        }

        @Override
        public void receiveConfigInfo(String configInfo) {
          log.info("Receive route config:{}", configInfo);
          List<RouteDefinition> routeDefinitions = JSON
              .parseArray(configInfo, RouteDefinition.class);
          for (RouteDefinition routeDefinition : routeDefinitions) {
            log.info("Update route:{}", routeDefinition.toString());
            save(routeDefinition);
          }
        }
      });
    } catch (Exception e) {
      log.error("Listening nacos gateway route failed.", e);
    }
  }
}
